home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / networking / amitcp / httpd.lha / httpd / http_mime.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-18  |  7.0 KB  |  309 lines

  1. /*
  2.  * http_mime.c: Sends/gets MIME headers for requests
  3.  * 
  4.  * Rob McCool
  5.  * 
  6.  */
  7.  
  8.  
  9. #include "httpd.h"
  10.  
  11. struct mime_ext {
  12.     char *ext;
  13.     char *ct;
  14.     struct mime_ext *next;
  15. };
  16.  
  17. #define hash(i) (isalpha(i) ? (tolower(i)) - 'a' : 26)
  18.  
  19. /* Hash table */
  20. struct mime_ext *types[27];
  21. struct mime_ext *forced_types;
  22. struct mime_ext *encoding_types;
  23.  
  24. int content_length;
  25. char content_type[MAX_STRING_LEN];
  26.  
  27. char location[MAX_STRING_LEN];
  28. static char last_modified[MAX_STRING_LEN];
  29. static char content_encoding[MAX_STRING_LEN];
  30. char http_accept[HUGE_STRING_LEN];
  31.  
  32. char auth_line[MAX_STRING_LEN];
  33.  
  34. void hash_insert(struct mime_ext *me) {
  35.     register int i = hash(me->ext[0]);
  36.     register struct mime_ext *p, *q;
  37.  
  38.     if(!(q=types[i])) {
  39.         types[i]=me;
  40.         return;
  41.     }
  42.     if((!(p=q->next)) && (strcmp(q->ext,me->ext) >= 0)) {
  43.         types[i]=me;
  44.         me->next=q;
  45.         return;
  46.     }
  47.     while(p) {
  48.         if(strcmp(p->ext,me->ext) >= 0) break;
  49.         q=p;
  50.         p=p->next;
  51.     }
  52.     me->next=p;
  53.     q->next=me;
  54. }
  55.  
  56. void kill_mime() {
  57.     register struct mime_ext *p,*q;
  58.     register int x;
  59.  
  60.     for(x=0;x<27;x++) {
  61.         p=types[x];
  62.         while(p) {
  63.             free(p->ext);
  64.             free(p->ct);
  65.             q=p;
  66.             p=p->next;
  67.             free(q);
  68.         }
  69.     }
  70.     p=forced_types;
  71.     while(p) {
  72.         free(p->ext);
  73.         free(p->ct);
  74.         q=p;
  75.         p=p->next;
  76.         free(q);
  77.     }
  78.     p=encoding_types;
  79.     while(p) {
  80.         free(p->ext);
  81.         free(p->ct);
  82.         q=p;
  83.         p=p->next;
  84.         free(q);
  85.     }
  86. }
  87.  
  88. void init_mime() {
  89.     char l[MAX_STRING_LEN],w[MAX_STRING_LEN],*ct;
  90.     FILE *f;
  91.     register struct mime_ext *me;
  92.     register int x,y;
  93.  
  94.     if(!(f = fopen(types_confname,"r"))) {
  95.         fprintf(stderr,"httpd: could not open mime types file %s\n",
  96.                 types_confname);
  97.         perror("fopen");
  98.         exit(1);
  99.     }
  100.  
  101.     for(x=0;x<27;x++) 
  102.         types[x] = NULL;
  103.     forced_types = NULL;
  104.     encoding_types = NULL;
  105.  
  106.     while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
  107.         if(l[0] == '#') continue;
  108.         cfg_getword(w,l);
  109.         ct = (char *)malloc(sizeof(char) * (strlen(w) + 1));
  110.         strcpy(ct,w);
  111.  
  112.         while(l[0]) {
  113.             cfg_getword(w,l);
  114.             me = (struct mime_ext *)malloc(sizeof(struct mime_ext));
  115.             me->ext = (char *)malloc(sizeof(char) * (strlen(w)+1));
  116.             for(x=0;w[x];x++)
  117.                 me->ext[x] = (islower(w[x]) ? w[x] : tolower(w[x]));
  118.             me->ext[x] = '\0';
  119.             me->ct=strdup(ct);
  120.             me->next=NULL;
  121.             hash_insert(me);
  122.         }
  123.         free(ct);
  124.     }
  125.     fclose(f);
  126. }
  127.  
  128. void dump_types() {
  129.     struct mime_ext *p;
  130.     register int x;
  131.  
  132.     for(x=0;x<27;x++) {
  133.         p=types[x];
  134.         while(p) {
  135.             printf("ext %s: %s\n",p->ext,p->ct);
  136.             p=p->next;
  137.         }
  138.     }
  139.     p=forced_types;
  140.     while(p) {
  141.         printf("file %s: %s\n",p->ext,p->ct);
  142.         p=p->next;
  143.     }
  144. }
  145.  
  146. int is_content_type(char *type) {
  147.     return(!strcmp(content_type,type));
  148. }
  149.  
  150. void set_content_type(char *file) {
  151.     int i,l,l2;
  152.     struct mime_ext *p;
  153.     char fn[MAX_STRING_LEN];
  154.  
  155.     strcpy(fn,file);
  156.     if((i=rind(fn,'.')) >= 0) {
  157.         ++i;
  158.         l=strlen(fn);
  159.         p = encoding_types;
  160.  
  161.         while(p) {
  162.             if(!strcmp(p->ext,&fn[i])) {
  163.                 fn[i-1] = '\0';
  164.                 if(content_encoding[0])
  165.                     sprintf(content_encoding,"%s, %s",content_encoding,p->ct);
  166.                 else
  167.                     strcpy(content_encoding,p->ct);
  168.                 if((i=rind(fn,'.')) < 0)
  169.                     break;
  170.                 ++i;
  171.                 l=strlen(fn);
  172.                 p=encoding_types;
  173.             }
  174.             else
  175.                 p=p->next;
  176.         }
  177.     }
  178.     p=forced_types;
  179.     l=strlen(fn);
  180.  
  181.     while(p) {
  182.         l2=l-strlen(p->ext);
  183.         if((l2 >= 0) && (!strcasecmp(p->ext,&fn[l2]))) {
  184.             strcpy(content_type,p->ct);
  185.             return;
  186.         }
  187.         p=p->next;
  188.     }
  189.  
  190.     if((i = rind(fn,'.')) < 0) {
  191.         strcpy(content_type,default_type);
  192.         return;
  193.     }
  194.     ++i;
  195.     p=types[hash(fn[i])];
  196.  
  197.     while(p) {
  198.         l2=l-strlen(p->ext);
  199.         if(!strcasecmp(p->ext,&fn[l2])) {
  200.             strcpy(content_type,p->ct);
  201.             return;
  202.         }
  203.         p=p->next;
  204.     }
  205.     strcpy(content_type,default_type);
  206. }
  207.  
  208. int scan_script_header(FILE *f, FILE *fd) {
  209.     char l[MAX_STRING_LEN];
  210.     char w[MAX_STRING_LEN];
  211.  
  212.     while(1) {
  213. #ifndef AMIGA
  214.         if(getline(l,MAX_STRING_LEN,fileno(f),timeout))
  215. #else
  216.         if(cfg_getline(l,MAX_STRING_LEN,f))
  217. #endif
  218.             die(SERVER_ERROR,"httpd: script failed to produce output",fd);
  219.  
  220.         if(l[0] == '\0') return is_url(location);
  221.         getword(w,l,':');
  222.         if(!strcasecmp(w,"Content-type"))
  223.             sscanf(l,"%s",content_type);
  224.         else if(!strcasecmp(w,"Location"))
  225.             sscanf(l,"%s",location);
  226.     }
  227. }
  228.  
  229. void add_type(char *fn, char *t) {
  230.     struct mime_ext *n=(struct mime_ext *)malloc(sizeof(struct mime_ext));
  231.  
  232.     n->ext = strdup(fn);
  233.     n->ct = strdup(t);
  234.     n->next = forced_types;
  235.     forced_types = n;
  236. }
  237.  
  238. void add_encoding(char *fn, char *t) {
  239.     struct mime_ext *n=(struct mime_ext *)malloc(sizeof(struct mime_ext));
  240.  
  241.     n->ext = strdup(fn);
  242.     n->ct = strdup(t);
  243.     n->next = encoding_types;
  244.     encoding_types = n;
  245. }
  246.  
  247. void set_content_length(int l) {
  248.     content_length = l;
  249. }
  250.  
  251. void set_last_modified(time_t t) {
  252.     strcpy(last_modified,gm_timestr_822(t));
  253. }
  254.  
  255. void get_mime_headers(int fd) {
  256.     char l[MAX_STRING_LEN];
  257.     char w[MAX_STRING_LEN];
  258.  
  259.     content_type[0] = '\0';
  260.     last_modified[0] = '\0';
  261.     content_length = -1;
  262.     auth_line[0] = '\0';
  263.     content_encoding[0] = '\0';
  264.     http_accept[0] = '\0';
  265.     location[0] = '\0';
  266.  
  267.     while(!(getline(l,MAX_STRING_LEN,fd,timeout))) {
  268.         getword(w,l,':');
  269.         if(!strcasecmp(w,"Content-type")) 
  270.             sscanf(l,"%s",content_type);
  271.         else if(!strcasecmp(w,"Authorization"))
  272.             strcpy(auth_line,l);
  273.         else if(!strcasecmp(w,"Content-length"))
  274.             sscanf(l,"%d",&content_length);
  275.         else if(!strcasecmp(w,"Accept")) {
  276.             if(http_accept[0])
  277.                 sprintf(http_accept,"%s, %s%c",http_accept,l,'\0');
  278.             else
  279.                 strcpy(http_accept,l);
  280.         }
  281.         else if(!l[0])
  282.             return;
  283.     }
  284. }
  285.  
  286. void dump_default_header(FILE *fd) {
  287.     fprintf(fd,"Date: %s%c",gm_timestr_822(time(NULL)),LF);
  288.     fprintf(fd,"Server: %s%c",SERVER_VERSION,LF);
  289.     fprintf(fd,"MIME-version: 1.0%c",LF);
  290. }
  291.  
  292. void send_mime_headers(FILE *fd) {
  293.     fprintf(fd,"%s %s%c",SERVER_PROTOCOL,
  294.             (location[0] ? "302 Found" : "200 OK"),LF);
  295.     dump_default_header(fd);
  296.     if(content_type[0])
  297.         fprintf(fd,"Content-type: %s%c",content_type,LF);
  298.     if(last_modified[0])
  299.         fprintf(fd,"Last-modified: %s%c",last_modified,LF);
  300.     if(content_length >= 0) 
  301.         fprintf(fd,"Content-length: %d%c",content_length,LF);
  302.     if(location[0])
  303.         fprintf(fd,"Location: %s%c",location,LF);
  304.     if(content_encoding[0])
  305.         fprintf(fd,"Content-encoding: %s%c",content_encoding,LF);
  306.  
  307.     fprintf(fd,"%c",LF);
  308. }
  309.